package com.example.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.example.entity.vo.response.WeatherVo;
import com.example.service.WeatherService;
import jakarta.annotation.Resource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;

import static com.example.utils.Const.FORUM_WEATHER_CACHE;

@Service
public class WeatherServiceImpl implements WeatherService {

    //发送请求
    @Resource
    private RestTemplate restTemplate;

    @Value("${spring.weather.key}")
    private String key;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    /**
     * 根据位置查询天气
     * @param longitude 经度
     * @param latitude 纬度
     * @return 封装好的信息
     */
    @Override
    public WeatherVo fetchWeather(double longitude, double latitude) {
        return this.fetchFromCache(longitude,latitude);
    }




    //从缓存中取
    private WeatherVo fetchFromCache(double longitude, double latitude){
        //获取天气
        byte[] data = restTemplate.getForObject(
                "https://geoapi.qweather.com/v2/city/lookup?location=" + longitude + "," + latitude + "&key=" + key, byte[].class);
        //获取到的是压缩的格式，需要解压
        JSONObject jsonData = decompressStingToJson(data);
        //判断
        if (jsonData == null) {return null;}
        //处理数据
        JSONObject location = jsonData.getJSONArray("location").getJSONObject(0);
        int id = location.getInteger("id");//地区Id
        String key = FORUM_WEATHER_CACHE+id;
        String cache = stringRedisTemplate.opsForValue().get(key);
        if (cache != null){
            //转成目标vo返回
            return JSONObject.parseObject(cache).to(WeatherVo.class);
        }
        //调用api
        WeatherVo vo = this.fetchFromAPI(id,location);
        if(vo == null)return null;
        stringRedisTemplate.opsForValue().set("key",JSONObject.from(vo).toJSONString(),1, TimeUnit.HOURS);
        return vo;
    }

    //缓存中没有，则通过api查询
    private WeatherVo fetchFromAPI(int id, JSONObject location){
        WeatherVo vo = new WeatherVo();
        vo.setLocation(location);
        JSONObject now = this.decompressStingToJson(restTemplate.getForObject(
                "https://devapi.qweather.com/v7/weather/now?location="+id+"&key="+key, byte[].class));
        if(now == null) return null;
        vo.setNow(now.getJSONObject("now"));
        JSONObject hourly = this.decompressStingToJson(restTemplate.getForObject(
                "https://devapi.qweather.com/v7/weather/24h?location="+id+"&key="+key, byte[].class));
        if(hourly == null) return null;
        vo.setHourly(new JSONArray(hourly.getJSONArray("hourly").stream().limit(5).toList()));
        return vo;
    }



    //将Gzip的数据解压成json
    private JSONObject decompressStingToJson(byte[] data){
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(data));
            byte[] buffer = new byte[1024];
            int read;
            while ((read = gzip.read(buffer)) != -1)
                stream.write(buffer, 0, read);
            gzip.close();
            stream.close();
            return JSONObject.parseObject(stream.toString());
        } catch (IOException e) {
            return null;
        }
    }

}
